﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using System.Xml;
using System.Globalization;
using PostIt.Interfaces;
using PostIt.Static;
using PostIt.Classes;

namespace PostIt
{
    public partial class MainForm : Form
    {
		private bool _isAlwaysOnTop = false;
		private double _trans = 1;
		private Font _font;
		private string _language;
        
        private Color DEFAULTCOLOR = Color.Yellow;
        private const int DEFAULTWIDTH = 185;
        private const int DEFAULTHEIGHT = 182;

        /// <summary>
        /// Used to hide the app from the "alt-tab"
        /// </summary>
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                // turn on WS_EX_TOOLWINDOW style bit
                cp.ExStyle |= 0x80;
                return cp;
            }
        }

        public MainForm()
        {
            InitializeComponent();
            this.MaximizedBounds = SystemInformation.WorkingArea;            
            this.TransparencyKey = Color.Fuchsia;
            this.KeyDown +=new KeyEventHandler(HandleKeyDown);

			this.FormClosing += new FormClosingEventHandler(FormClose);
            notifyIcon1.Icon = AppResources.Icon1;

			this.SetStyle(
				ControlStyles.UserPaint |
				ControlStyles.AllPaintingInWmPaint |
				ControlStyles.OptimizedDoubleBuffer, true);

            LoadData();
			//Translation.LoadText("NsNotes.xml");

        }

		void FormClose(object sender, FormClosingEventArgs e)
		{
			Save();
			this.notifyIcon1.Visible = false;
			this.notifyIcon1.Dispose();
		}

        private void CreatePostIt(int x, int y, string text, Color color, int width, int height, List<string> attatchedFiles)
        {
            // TODO: Bajs. The whole process of creating/loading/saving notes should be somewhere else. I hope, I think, I know?            
            NsNoteForm form = new NsNoteForm();
            form.Text = text;
            form.X = x;
            form.Y = y;           
            
            if(attatchedFiles != null && attatchedFiles.Count > 0) 
                form.AddAttatchments(attatchedFiles);

            form.Width = width;
            form.Height = height;
            form.NoteBackColor = color;
			form.Font = this._font;
            form.KeyDown += new KeyEventHandler(HandleKeyDown);
            form.StartPosition = FormStartPosition.Manual;
            form.Show();
			form.ChangeOpacity(this._trans);

			if (_isAlwaysOnTop)
				form.ToggleAlwaysOnTop();
        }

        private void HandleKeyDown(object sender, KeyEventArgs e)
        {
			if (e.Control && e.KeyCode == Keys.N)
            {
                CreatePostIt(MousePosition.X,MousePosition.Y,"",DEFAULTCOLOR,DEFAULTWIDTH,DEFAULTHEIGHT, null);
                
                e.Handled = true;
                return; 
            }

            if(e.Control && e.KeyCode == Keys.P)
            {
                AddNoteFromClipboard();
            }

            if (e.Control && e.KeyCode == Keys.C)
            {
                IPostit p = ((IPostit) sender);
                
                if(p != null)
                    SetClipboard(p.ToString());
            }



            if (e.Control && e.KeyCode == Keys.Q)
            {
                Save();
                e.Handled = true;
                Application.Exit();
            }

            if (e.Control && e.KeyCode == Keys.T)
            {
				if (!_isAlwaysOnTop)
				{
					_isAlwaysOnTop = true;
					ToggleAlwaysOnTop();
				}
				else
				{
					_isAlwaysOnTop = false;
					ToggleAlwaysOnTopOff();
				}

                e.Handled = true;
				return;
            }

            if (e.Control && e.KeyCode == Keys.O)
            {
                OrderNotes(this, null); // :(
            }
        }

        private void LoadData()
        {
            this.Controls.Clear();
			LoadSettings();
			LoadNotes(); 
        }

        private void LoadNotes()
        {
            XmlDocument doc = new XmlDocument();
            try
            {
                doc.Load("notes.xml");
            }
            catch (FileNotFoundException)
            {
                return;
            }
            catch (Exception e)
            {
                MessageBox.Show("Något gick fel vid laddning av Notes.xml (" + e.Message + ")");
                return;
            }

            XmlNodeList list = doc.GetElementsByTagName("postit");

            foreach (XmlElement element in list)
            {
                int x = 0, y = 0;
                var c = DEFAULTCOLOR;
                var text = "";
                int width = DEFAULTWIDTH;
                int height = DEFAULTHEIGHT;
                List<string> attatchedFiles = new List<string>();

                foreach (XmlNode node in element.ChildNodes)
                {
                    if (node.Name == "xPos")
                    {
                        x = int.Parse(node.InnerText);
                        continue;
                    }

                    if (node.Name == "yPos")
                    {
                        y = int.Parse(node.InnerText);
                        continue;
                    }

                    if (node.Name == "Text")
                    {
                        text = node.InnerText;
                        if (!string.IsNullOrEmpty(text))
                            text = text.Replace("\t", "    ");
                        continue;
                    }

                    if (node.Name == "color")
                    {
                        c = Color.FromName(node.InnerText);
                        continue;
                    }

                    if(node.Name == "width")
                    {
                        width = int.Parse(node.InnerText);
                        continue;
                    }

                    if(node.Name == "height")
                    {
                        height = int.Parse(node.InnerText);
                        continue;
                    }

                    if(node.Name == "attatchedfiles")
                    {
                        foreach (XmlNode fileNode in node.ChildNodes)
                        {
                            attatchedFiles.Add(fileNode.InnerText);
                        }
                        continue;
                    }
                }

                CreatePostIt(x, y, text, c, width, height, attatchedFiles);
            }
        }

        private void Save()
        {
            SaveNotes();
			SaveSettings();
        }

        /// <summary>
        /// Sparar vanliga anteckningar
        /// </summary>
        private void SaveNotes()
        {
            var writer = new XmlTextWriter("notes.xml", null);
            writer.Formatting = Formatting.Indented;

            writer.WriteStartDocument();            
            writer.WriteStartElement("Notes");
            

            if (Application.OpenForms != null)
                    foreach (var note in Application.OpenForms.OfType<NsNoteForm>())
                    {
                        writer.WriteStartElement("postit");
                            writer.WriteStartElement("Text", "");
                                writer.WriteString(note.Text);
                            writer.WriteEndElement();

                            writer.WriteStartElement("xPos");
                                writer.WriteString(note.X.ToString());
                            writer.WriteEndElement();
 
                            writer.WriteStartElement("yPos");
                                writer.WriteString(note.Y.ToString());
                            writer.WriteEndElement();
  
                            writer.WriteStartElement("color");
                                writer.WriteString(note.NoteBackColor.ToKnownColor().ToString());
                            writer.WriteEndElement();
                        
                            writer.WriteStartElement("width");
                                writer.WriteString(note.Width.ToString());
                            writer.WriteEndElement();

                            writer.WriteStartElement("height");
                                writer.WriteString(note.Height.ToString());
                            writer.WriteEndElement();
                            
                            if(note.AttatchedFiles.Count > 0)
                            {
                                writer.WriteStartElement("attatchedfiles");
                                foreach (var file in note.AttatchedFiles)
                                {
                                    writer.WriteStartElement("file");
                                        writer.WriteString(file);
                                    writer.WriteEndElement();
                                }
                                writer.WriteEndElement();
                            }

                        writer.WriteEndElement();
                    }

            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Close();
        }

        private static void ShowHideNotes()
        {
			foreach (Form f in Application.OpenForms)
			{
				f.Show();
				f.WindowState = FormWindowState.Normal;
				f.Activate();
			}
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
               ShowHideNotes();
        }

        private void avslutaToolStripMenuItem_Click(object sender, EventArgs e)
        {
           var r = MessageBox.Show(AppResources.ExitApplicationConfirm,AppResources.ExitApplicationConfirmTitle, MessageBoxButtons.YesNo);
           if (r == DialogResult.Yes)
           {
               Save();
               Application.Exit();
           }
        }

        private void showHideToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ShowHideNotes();
        }


        private void addNoteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreatePostIt(100, 100, "", DEFAULTCOLOR,DEFAULTWIDTH,DEFAULTHEIGHT, null);
        }

        private void tsmAlwaysOnTop_Click(object sender, EventArgs e)
        {
			if (!_isAlwaysOnTop)
			{
				_isAlwaysOnTop = true;
				ToggleAlwaysOnTop();

			}
			else
			{
				_isAlwaysOnTop = false;
				ToggleAlwaysOnTopOff();
			}
        }

        private static void ToggleAlwaysOnTop()
        {
            foreach (IPostit note in Application.OpenForms.OfType<IPostit>())
            {
                note.ToggleAlwaysOnTop();
            }
        }

        private void ToggleAlwaysOnTopOff()
		{
		    foreach (IPostit note in Application.OpenForms.OfType<IPostit>())
		        note.ToggleAlwaysOnTopOff();
		    
		}

        private void toolStripMenuItemAbout_Click(object sender, EventArgs e)
		{
			MessageBox.Show(@"NSPostIt version: " + Application.ProductVersion + Environment.NewLine + Environment.NewLine + AppResources.NsNotesAboutText);
		}

		private void toolStripMenuItemSettings_Click(object sender, EventArgs e)
		{
			FormSettings form = new FormSettings();
            form.OnSettingsChanged += new SettingsChangedHandler(form_OnSettingsChanged);
			form.ShowDialog();
		}

        void form_OnSettingsChanged(object sender, SettingsChangedHandlerArgs args)
        {
            this._font = FontCreater.GetSpecialFont(args.FontName, args.Size);
            foreach (IPostit note in Application.OpenForms.OfType<IPostit>())
            {
                    note.ChangeFont(this._font);
            }
            SaveSettings();
        }

		/// <summary>
		/// Changes the opacity for all the forms
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void SetOpacity(object sender, EventArgs e)
		{
			NumberFormatInfo formater = new NumberFormatInfo();
			formater.NumberDecimalSeparator = ".";
			double ob = Convert.ToDouble(((ToolStripMenuItem)sender).Tag.ToString(), formater);
			foreach (IPostit postit in Application.OpenForms.OfType<IPostit>())
			{
			    postit.ChangeOpacity(ob);
			}
			this._trans = ob;
		}

		/// <summary>
		/// Search all the notes when the user presses enter
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void toolBarSearchNotes(object sender, KeyPressEventArgs e)
		{
			if (e.KeyChar == '\r')
			{
				foreach (Form f in Application.OpenForms)
				{
					if (f is IPostit)
					{
						IPostit postit = (IPostit)f;
                        bool b = postit.Search(toolStripTextBox1.Text);
						if (!b)
                            postit.HidePostIt();
						else
                            postit.ShowPostIt();
                        
					}
				}

				e.Handled = true;
			}
		}

		/// <summary>
		/// Saves the settings to settings.xml
		/// </summary>
		private void SaveSettings()
		{
			var writer = new XmlTextWriter("settings.xml", null);
		    writer.Formatting = Formatting.Indented;

            writer.WriteStartDocument();
			writer.WriteStartElement("settings");

			writer.WriteStartElement("alwaysontop");
			writer.WriteString(this._isAlwaysOnTop.ToString());
			writer.WriteEndElement();

			writer.WriteStartElement("transparency");
			writer.WriteString(this._trans.ToString());
			writer.WriteEndElement();

			writer.WriteStartElement("font");
			writer.WriteAttributeString("size", this._font.Size.ToString());
			writer.WriteString(this._font.Name+".ttf");
			writer.WriteEndElement();

			writer.WriteEndElement();
			writer.WriteEndDocument();

			writer.Close();
		}

		/// <summary>
		/// Loads all settings from settings.xml
		/// </summary>
		private void LoadSettings()
		{
			XmlDocument doc = new XmlDocument();
			try
			{
				doc.Load("settings.xml");
			}
			catch (FileNotFoundException)
			{
				this._font = FontCreater.GetSpecialFont("Al-seana.ttf", 24);
				this._isAlwaysOnTop = false;
				this._trans = 1;
				return;
			}
			catch (Exception e)
			{
                MessageBox.Show(AppResources.ErrorLoadSettingsMessage + e.Message);
                this._font = FontCreater.GetSpecialFont("Al-seana.ttf", 24);
                this._isAlwaysOnTop = false;
                this._trans = 1;
				return;
			}

			try
			{
				XmlNodeList list = doc.GetElementsByTagName("settings");
				foreach (XmlElement element in list)
				{
					foreach (XmlNode node in element.ChildNodes)
					{
						if (node.Name == "alwaysontop")
						{
							this._isAlwaysOnTop = bool.Parse(node.InnerText);
							continue;
						}

						if (node.Name == "transparency")
						{
							var formater = new NumberFormatInfo {NumberDecimalSeparator = "."};

						    double op = Convert.ToDouble(node.InnerText.Replace(",", "."), formater);
							this._trans = op;
							continue;
						}

						if (node.Name == "font")
						{
							float size = float.Parse(node.Attributes[0].Value);
							this._font = FontCreater.GetSpecialFont(node.InnerText, size);
							continue;
						}
					}
				}
			}
			catch (Exception e)
			{
				MessageBox.Show(AppResources.ErrorLoadSettingsMessage + e.Message);
				this._font = FontCreater.GetSpecialFont("Al-seana.ttf", 24);
				this._isAlwaysOnTop = false;
				this._trans = 1;
			}
		}

        private void OrderNotes(object sender, EventArgs e)
        {
            int x, y;
            y = SystemInformation.WorkingArea.Height;
            x = SystemInformation.WorkingArea.Width;

            int howManyX = x / 185;
            int placedY = 0;
            int currX = 1;
            int currY = 1;

            	foreach (IPostit note in Application.OpenForms.OfType<IPostit>())
            	{
            	    if (placedY == howManyX)
            	    {
            	        currY = currY + 182;
            	        placedY = 0;
            	        currX = 1;
            	    }
            	    note.SetScreenPos(currX, currY);
            	    currX = currX + 185;
            	    placedY = placedY + 1;
            	}
        }

        private void AddNoteFromClipboard()
        {
            if (Clipboard.ContainsText(TextDataFormat.Text))
            {
                string text = Clipboard.GetText(TextDataFormat.Text);
                CreatePostIt(100, 100, text, DEFAULTCOLOR, DEFAULTWIDTH, DEFAULTHEIGHT,null);
            }
        }

        private void toolStripAddFromClipboard_Click(object sender, EventArgs e)
        {
            AddNoteFromClipboard();
        }

        private void SetClipboard(string text)
        {
            if(!string.IsNullOrEmpty(text))
                Clipboard.SetText(text);
        }
    }
}
